<html>
<head>
<title>Example Screen Savers</title>
<style type="text/css">
strong {text-transform: uppercase;}
li {margin-top: 1ex; margin-bottom: 1ex;}
h1, h2 {padding-bottom: 0.2ex;}
h2 {margin-top: 4ex;}
</style>
</head>

<h1 style="margin-bottom: 0; border-bottom: solid thin red;">Example Screen Savers</h1>
<p style="margin-top: 0;">(c) 1996-2003 Lucian Wischik, <a href="http://www.wischik.com/scr">www.wischik.com/scr</a></p>


<p><strong>Question:</strong> <em>How to design the best "screensaver framework?"</em></p>

<p><strong>Answer:</strong> After seven years experience in designing savers and frameworks,
my final conclusion is -- <strong>don't</strong>. Don't make a framework.
Instead, make a complete, self-contained, minimal saver that
doesn't impose any structure on the programmer and doesn't
require to be "learnt". Keep it simple.
Accordingly, I present five very basic screen savers.
They cover most of the important areas:</p>
<ul>
<li><i>jpegs, bitmaps, transparency
for sprites, playing audio, listening to audio, using zipped datafiles
embeded as resources rather than as separate files, 3d-opengl, changing screen mode,
multi-monitor support, Plus!-style configuration dialogs,
passwords under Win95/98/ME, and installation/uninstallation.</i></li></ul>

<p>These examples complement my technical article,
<a href="http://www.wischik.com/scr/howtoscr.html">How To Write a 32bit 
Screen Saver</a>. That article goes into exhaustive detail about exactly
how a saver must behave. To understand the internals of these examples,
read the article.</p>


<p>Here's what else I've learnt -- the following guidelines,
along with the example code,
is the distilled "best practice" from years of programming
savers and millions of downloads. These guidelines will reduce the
effort to design, debug and distribute your savers, and will reduce the
number of support-emails you have to answer:</p>

<ul>

<li><strong>Use global variables</strong> for the saver's settings. I know this goes
against one's normal instinct, but in this case a saver's settings
are inherently global: they're loaded from the registry upon startup,
modified by the configuration dialog, and saved to the registry when
you click the "OK" button. There's no need to keep multiple copies
of them. Just make them global.</li>

<li><strong>Allocate resources lazily</strong> (ie. upon first use) so far as possible.
That means: initialize a global handle or pointer to 0, and in your
OnPaint handler or wherever where you first use it, then check whether
it's still 0 and if so create it. The check gets performed every single
cycle, but it's not costly.

<li><strong>Combine installer/uninstaller/saver</strong> in a single executable. That is,
create a single executable called "saver_setup.EXE". When the user runs
it, it installs itself (including uninstall support) by copying itself
into the Windows directory but renamed as "saver.SCR". There it behaves
like a normal saver. When it's run with the argument /u, it behaves like
an uninstaller.</li>

<li><strong>Single self-contained file</strong> for the saver. Don't use any additional
files: instead, embed all your artwork and music as resources within the
saver. This means you have to compress them. I have included example
savers to show how to uncompress and use resources that are OGG music
files, ZIP files, JPEG pictures. I rewrote the standard public OGG and
ZIP source code to make them easier to use, and (in the latter case)
to avoid the need for temporary files: instead, zipping happens directly
from resource to memory buffer.</li>

<li><strong>Watch for gradual leaks</strong>. A screen saver might run for hours or days
on end. If there is any memory or resource leak, it will eventually
cause problems. Be very careful, and use the Task Manager to monitor
program size and GDI heap.</li>

<li><strong>Multiple monitors</strong> - their time has come. Program from the
ground up with multi-monitors in mind. It's usually too hard to retrofit support
at a latter stage. Plan in advance: which variables are global (shared
between all screens and maybe also the configuration dialog), which are
specific to a particular screen. Music, for instance, shouldn't be played
by every monitor's saver window.</li>

<li><strong>Use plain Win32 API</strong>. This gives smallest filesizes, and gives the
greatest control over the saver's behaviour. Also, you will still be
able to read and compile your source code in the future, since it's
not tied to any version of any particular development environment.</li>

<li><strong>Beware bandwidth</strong>. After putting a saver online in
August 2002, I suddenly noticed in September that it had been downloaded
hundreds of thousands of times and lumped me with a US$400 bill for
excess bandwidth. Be careful!</p>

</ul>



<h2 style="border-bottom: solid thin red;">Debugging and Deployment</h2>

<p style="margin-bottom: 0;">Copy the "scrprev.exe" utility into your Windows directory.
Test the saver with arguments</p>
<table style="margin-top: 0; margin-left: 3em;" cellspacing=0 cellpadding=0>
<tr><td>/c</td><td><i>to run the settings dialog</i></td></tr>
<tr><td>/p scrprev&nbsp;&nbsp;</td><td><i>to test in preview mode</i></td></tr>
<tr><td>/s</td><td><i>to run full-screen</i></td></tr>
<tr><td>/sm</td><td><i>to test multi-monitor behaviour</i></td></tr>
</table>

<p>Note: <tt>const tstring DebugFile=_T("OutputDebugString")</tt>
at the start of the file.
This will log interesting events, and will also run the saver in "friendly"
mode (i.e. not topmost, doesn't quit as soon as it looses focus or the
mouse moves). Before deployment you MUST change this.</p>

<p>Make sure you change the two STRINGTABLE resources: 1 is the name of the
saver, and 2 is its url for Add/Remove Programs. (you can remove 2
if there isn't a web page).</p>

<p>When you have finished, rename the saver to "mysaver_setup.exe" and deploy
it. The extension ".exe" will make the auto-self-installer happen when
the user double-clicks on it.</p>





<h2 style="border-bottom: solid thin red;">The Example Savers</h2>

<p>To create a new saver, I copy the directory from an old
one, rename all the files, open them all up in Notepad
and alter the names using search/replace. Don't forget
the STRINGTABLE resources in the .rc file, and the
VERSIONINFO, and the manifest.</p>

<p style="margin-bottom: 0;">There are project files for Visual C++6, Visual C++ .NET
and Borland C++Builder5. I'm sure the code will work fine
under other compilers. If you want, you can delete the project
files for compilers you're not using. The extensions are:</p>
<table style="margin-top: 0; margin-left: 3em;" cellspacing=0 cellpadding=0>
<tr><td>.sln .vcprog</td><td><i>Visual Studio .NET workspace / project</i></td></tr>
<tr><td>.dsw .dsp</td><td><i>Visual C++6 workspace / project</i></td></tr>
<tr><td>.bpg .bpf .bpr&nbsp;&nbsp;</td><td><i>Borland C++Builder group / project</i></td></tr>
</table>

<p>Each example has pretty much the same structure. All the saver
code is contained in a single .cpp file that looks like this:</p>

<table style="margin-left: 3em; border: solid 1px black; background-color: rgb(222,242,154);">
<tr><td style="padding: 2ex;">
<p><i>// Comments at the top about how it works and how</i><br>
<i>// to achieve the same in your own savers.</i></p>
<p>A bunch of header declarations</p>
<p><i>// ---------------------------------------------</i></p>
<p>The code that's unique to each saver. This is<br>
the important code to read.</p>
<p><i>// ---------------------------------------------</i></p>
<p>Then comes the generic saver code that's<br>
common to all of them.</p>
</td></tr></table>

<p><strong>MinScr</strong> -- this saver doesn't do anything special,
just blobs on the
screen using double-buffering. It's a good starting point.</p>

<p><strong>Images</strong> -- this saver uses images. It draws a sprite (BMP with
transparency) on top of a background (JPG). What's special is
that it stores the sprite and background compressed in a ZIP file,
and this zip is in turn stored as a resource in the .SCR file.
At runtime, when the images are needed, they're decompressed
directly from resource into memory without any intermediate files.</p>

<p><strong>PlayOgg</strong> -- this saver plays music from an OGG file that's embedded
as a resource. I used to think music in a screen saver was silly
(because savers are run when you're not at the computer!) But I
was wrong: for some of my musical savers, I've had lots of happy
parents write to me that their young children are transfixed by
the combination of music and images. OGG is a file format that's
like MP3 only better.</p>

<p><strong>AudioIn</strong> -- this saver captures the currently-playing sound (be
it from CD or Windows Media Player or whatever) and displays
a voiceprint of it.</p>

<p><strong>ThreeDee</strong> -- uses OpenGL for hardware-accelerated 3D graphics. Also
optionally changes the screen mode, so as to run faster. There
are lots of troublesome fiddly issues to do with 3d graphics and
with mode changing: read the comments at the start of threedee.cpp.</p>




<p style="font-size: xx-small; border-top: solid 1px black; margin-top: 6em;">
By <a href="http://www.wischik.com/lu">Lucian Wischik</a>, University of Bologna. June 2003.</p>
